﻿using StateMachine;
using System;

namespace FrameworksTests.StateMachineTests
{
    internal class FiniteStateMachineHelper
    {
        public enum TestState
        {
            First,
            Second,
            Third
        }

        public class TestStateMachine : FiniteStateMachine<TestState>
        {
            public TestStateMachine(TestStateMachineContext context)
                : base(context)
            {
                this.RegisterStateHandler(TestState.First, new FirstStateHandler(context));
                this.RegisterStateHandler(TestState.Second, new SecondStateHandler(context));
                this.RegisterStateHandler(TestState.Third, new ThirdStateHandler(context));
            }

            public TestState CurrentState
            {
                get
                {
                    return this.Context.State;
                }
            }
        }

        public class TestStateMachineContext : StateMachineContext<TestState>
        {
            public TestStateMachineContext(TestState initialState)
                : base(initialState)
            {
            }
        }

        public abstract class TestStateHandlerBase : StateHandler<TestState>
        {
            private readonly TestState state;

            public TestStateHandlerBase(TestState state, TestStateMachineContext context)
                : base(context)
            {
                this.state = state;
            }

            protected override TestState HandleInputOverride(object input)
            {
                Array values = Enum.GetValues(typeof(TestState));
                int currentIndex = Array.IndexOf(values, this.state);
                int nextIndex = (currentIndex + 1) % values.Length;
                TestState nextValue = (TestState)(values.GetValue(nextIndex));

                return nextValue;
            }
        }

        public class FirstStateHandler : TestStateHandlerBase
        {
            public FirstStateHandler(TestStateMachineContext context)
                : base(TestState.First, context)
            {
            }
        }

        public class SecondStateHandler : TestStateHandlerBase
        {
            public SecondStateHandler(TestStateMachineContext context)
                : base(TestState.Second, context)
            {
            }
        }

        public class ThirdStateHandler : TestStateHandlerBase
        {
            public ThirdStateHandler(TestStateMachineContext context)
                : base(TestState.Third, context)
            {
            }
        }
    }
}
